package cn.bonoon.kernel.support.searcher;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.context.ApplicationContext;

import cn.bonoon.kernel.bytecode.BytecodeFactory;
import cn.bonoon.kernel.bytecode.EntityReader;
import cn.bonoon.kernel.bytecode.QueryConverter;
import cn.bonoon.kernel.events.ReadEvent;
import cn.bonoon.kernel.support.ProxyEntityManager;
import cn.bonoon.kernel.support.entities.Persistable;

/**
 * <pre>
 * 1. 使用查询条件，会自动解析、缓存针对该实体进行查询的查询条件类型
 * 
 * 2. 把对象转为指定类型，会自动解析、缓存针对该实体进行转值的普通界面实体对象
 * 
 * </pre>
 * @author jackson
 *
 * @see BaseSearcher
 */
public class StandardSearcher extends BaseSearcher implements ISearcher{
	protected static final float LOAD_FACTOR = 0.75f;
	protected static final int CONCURRENCY_LEVEL = 2, INITIAL_CAPACITY = 4;
	
	protected final ApplicationContext applicationContext;
	
	private final Map<Class<?>, EntityReader> valueReaders;
	private final Map<Class<?>, QueryConverter> queryConverters;
	
	public StandardSearcher(Class<? extends Persistable> entityClass, ApplicationContext applicationContext){
		super(entityClass);
		this.valueReaders = new ConcurrentHashMap<>(INITIAL_CAPACITY, LOAD_FACTOR, CONCURRENCY_LEVEL);
		this.queryConverters = new ConcurrentHashMap<>(INITIAL_CAPACITY, LOAD_FACTOR, CONCURRENCY_LEVEL);
		
		this.applicationContext = applicationContext;
	}
	
	public StandardFinder finder(ProxyEntityManager manager, ReadEvent readEvent, Class<?> resultClassType)throws Exception{
		return initFinder(new ExtendFinder(getEntityReader(resultClassType), readEvent, manager));
	}
	
	public QueryConverter getQueryConverter(Class<?> cc) throws Exception{
		QueryConverter qc = queryConverters.get(cc);
		if(null == qc){
			qc = BytecodeFactory.query(applicationContext, cc, entityDescriptor);
			queryConverters.put(cc, qc);
		}
		return qc;
	}
	
	public EntityReader getEntityReader(Class<?> rc) throws Exception{
		EntityReader er = valueReaders.get(rc);
		if(null == er){
			er = BytecodeFactory.reader(applicationContext, rc, entityDescriptor);
			valueReaders.put(rc, er);
		}
		return er;
	}

//	@Override
//	public <O> List<O> tryLoadRoot(ReadEvent readEvent, Class<O> resultClassType) throws Exception {
//		// TODO Auto-generated method stub
//		return null;
//	}
//
//	@Override
//	public <O> List<O> tryLoadChildren(Long rid, ReadEvent readEvent, Class<O> resultClassType) throws Exception {
//		// TODO Auto-generated method stub
//		return null;
//	}
}
